package com.webemail.email.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sun.mail.imap.IMAPFolder;
import com.webemail.email.entity.Email;
import com.webemail.email.entity.MyFolder;
import com.webemail.email.mapper.MyFolderMapper;
import com.webemail.email.service.MyEmailService;
import com.webemail.email.service.MyFolderService;
import com.webemail.sys.model.SysEmailAccount;
import com.webemail.sys.service.EmailService;
import com.webemail.sys.util.MailBean;
import com.webemail.sys.util.MailConnect;
import com.webemail.sys.util.MailUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.*;
import java.io.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LaiHQ
 */
@Service
public class MyFolderServiceImpl extends ServiceImpl<MyFolderMapper,MyFolder> implements MyFolderService {

    @Autowired
    private EmailService emailService;
    @Autowired
    private MyFolderMapper myFolderMapper;
    @Autowired
    private MyEmailService myEmailService;

    /**
     * 查询我的所有文件夹
     *
     * @return
     */
    @Override
    public List<MyFolder> syncFolder() throws MessagingException {
        SysEmailAccount account = getCurrAccount();
        this.checkSync(account);

        List<Folder> serviceFolderList = this.getServiceFolderList(account,"INBOX");
        if (ObjectUtil.isEmpty(serviceFolderList)){
            return Collections.emptyList();
        }
        Folder folder = serviceFolderList.get(0);

        //递归存储
        recursionSaveFolder(account.getAccount(),folder,-1L);

        //根据文件名对比已有目录,这里不能删除,只能抛出异常,提醒用户去手动修改系统的文件夹名
        return null;
    }

    /**
     * 查询我的全部文件夹
     *
     * @return
     */
    @Override
    public List<MyFolder> getMyFolder() {
        List<MyFolder> myFolders = myFolderMapper.selectList(Wrappers.lambdaQuery(MyFolder.class)
                .eq(MyFolder::getUserId, 1));

        return myFolders;
    }

    /**
     * 获取最新邮件
     *
     * @return
     */
    @Override
    public void checkSync(SysEmailAccount account) {
        List<Folder> serviceFolderList = this.getServiceFolderList(account,"INBOX*");
        List<MyFolder> myFolders = this.getMyFolder();
        if(serviceFolderList.size() < myFolders.size()){
            throw new RuntimeException("请手动同步系统文件夹!");
        }

        List<String> serviceFolderNames = serviceFolderList.stream().map(Folder::getFullName)
                .collect(Collectors.toList());
        for(MyFolder mf:myFolders){
            if(!serviceFolderNames.contains(mf.getFullName())){
                throw new RuntimeException("请手动同步系统文件夹!");
            }
        }
    }

    /**
     * 获取服务器端邮箱目录
     *
     * @return
     */
    @Override
    public List<Folder> getServiceFolderList(SysEmailAccount account,String pattern) {
        Store store = getStore(account);
        if(ObjectUtil.isEmpty(store)){
            return Collections.emptyList();
        }
        //查询所有目录
        Folder[] folders = new Folder[0];
        try {
            folders = store.getDefaultFolder().list(pattern);
//            folders = store.getDefaultFolder().list("INBOX*");
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        if (folders.length <1){
            return Collections.emptyList();
        }
        return Arrays.asList(folders);
    }

    /**
     * 获取store
     * @param account
     * @return
     */
    @Override
    public Store getStore(SysEmailAccount account){
        MailBean re;
        MailConnect mailConnect;
        try {
            re = MailUtils.getLsReMailBean(account);
            mailConnect = new MailConnect(re);
            mailConnect.checkProperties();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        if (mailConnect.getState() != 0) {
            return null;
        }
        mailConnect.init();

        Store store = mailConnect.getStore();
        return store;
    }

    private void recursionSaveFolder(String account,Folder f,Long pid) throws MessagingException {
        String fullName = f.getFullName();
        List<MyFolder> folderList = myFolderMapper.selectList(Wrappers.lambdaQuery(MyFolder.class)
                .eq(MyFolder::getAccount, account)
                .eq(MyFolder::getFullName, fullName));
        MyFolder mf;
        if(ObjectUtil.isEmpty(folderList)){
            mf = new MyFolder();
            mf.setUserId(1L);
            mf.setAccount(account);
            mf.setCreateTime(new Date().toString());
            mf.setCreateUser("1");
            mf.setFullName(fullName);
            if(ObjectUtil.equals(fullName,"INBOX")){
                mf.setName("收件箱");
            }else{
                mf.setName(fullName.substring(fullName.lastIndexOf("/")+1));
            }
            mf.setPid(pid);
            myFolderMapper.insert(mf);
        }else{
            mf = folderList.get(0);
        }
        myEmailService.syncEmail(mf.getId(),f, f.getFullName(), account);
        Folder[] list = f.list();
        if(ObjectUtil.isEmpty(list)){
            return;
        }
        for (Folder subF:list) {
            recursionSaveFolder(account,subF,mf.getId());
        }
    }


    /**
     * 根据文件夹id删除邮件
     *
     * @return
     */
    @Override
    public int deleteEmailByFolderId() {
        return 0;
    }

    /**
     * 创建系统文件夹, 需要在服务器上创建对应的文件夹
     *
     * @return
     */
    @Override
    public boolean addFolder(Long folderId,String newName) {
        MyFolder myFolder = myFolderMapper.selectById(folderId);
        SysEmailAccount account = getCurrAccount();
        List<Folder> serviceFolderList = this.getServiceFolderList(account, myFolder.getFullName());
        if(ObjectUtil.isEmpty(serviceFolderList)){
            return false;
        }
        Folder folder = serviceFolderList.get(0);
        try {
            if(!folder.isOpen()){
                folder.open(Folder.READ_WRITE);
            }
            Store store = folder.getStore();
            Folder newFolder = store.getFolder(myFolder.getFullName() + "/" + newName);
            boolean createFlag = newFolder.create(Folder.HOLDS_FOLDERS);
            System.out.println(createFlag);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public SysEmailAccount getCurrAccount(){
        List<SysEmailAccount> accountList = emailService.list(1);
        if(ObjectUtil.isEmpty(accountList)){
            throw new RuntimeException("不存在当前账户");
        }

        SysEmailAccount account = accountList.get(0);
        return account;
    }

    /**
     * 更新文件夹名字,这里只能改本系统的名字,因为邮件系统的名称更改不会同步到系统,
     * 用户若手动修改了目录名字, 需要自己手动同步
     *
     * @param name
     * @return
     */
    @Override
    public boolean editFolderName(String name) {
        //当系统中存在, 服务上有不存在, 必须手动在系统把名字统一才能后续操作
        return false;
    }

    /**
     * 移动邮件, 需要过滤标题和内容,把邮件分为有案号或者没有案号的部分,匹配后需要移动到对应的文件夹
     *
     * @return
     */
    @Override
    public boolean moveEmail(Long emailId,Long targetFolderId) {
        SysEmailAccount currAccount = getCurrAccount();
        Store store = getStore(currAccount);
        Assert.notNull(store,"创建store失败!");
        Email email = myEmailService.getById(emailId);
        MyFolder myFolder = this.getById(targetFolderId);
        String sourceFullName = email.getFolderFullName();
        String targetFullName = myFolder.getFullName();

        try {
            Folder sourceFolder = store.getFolder(sourceFullName);
            if(!sourceFolder.isOpen()){
                sourceFolder.open(Folder.READ_WRITE);
            }
            Folder targetFolder = store.getFolder(targetFullName);
            if(!targetFolder.isOpen()){
                targetFolder.open(Folder.READ_WRITE);
            }
            IMAPFolder sourceIMAPFolder = (IMAPFolder) sourceFolder;
            Message message = sourceIMAPFolder.getMessageByUID(email.getUid());
            Assert.notNull(message,"服务器上未发现该邮件!");
            Message[] messages = new Message[1];
            messages[0] = message;
            //复制
            sourceFolder.copyMessages(messages,targetFolder);
            //删除原邮件
            sourceFolder.setFlags(messages, new Flags(Flags.Flag.DELETED), true);
            //标记永久删除
            sourceFolder.expunge();
            //删除系统的邮件
            myEmailService.removeById(emailId);
        } catch (MessagingException e) {
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 上传邮件
     *
     * @param emailId
     * @return
     */
    @Override
    public boolean uploadEmail(Long emailId) {
        Email email = myEmailService.getById(emailId);
        SysEmailAccount currAccount = getCurrAccount();
        Store store = getStore(currAccount);
//        File emlFile = new File(email.getTitle()+".eml");
        // 1. 邮件转EML字节流
        MultipartFile multipartFile = null;
        ByteArrayOutputStream emlStream = new ByteArrayOutputStream();
        try(BufferedOutputStream bos = new BufferedOutputStream(emlStream)) {
            IMAPFolder folder = (IMAPFolder)store.getFolder(email.getFolderFullName());
            Message message = folder.getMessageByUID(email.getUid());
            message.writeTo(bos);
            byte[] bytes = emlStream.toByteArray();
            multipartFile = new MockMultipartFile(email.getTitle()+".eml"
                    ,email.getTitle()+".eml", "text/plain", bytes);
        } catch (MessagingException | FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
//        ResultMsg resultMsg = uploadFile(multipartFile);
        JSONObject result = (JSONObject) JSON.toJSON("resultMsg.getData()");
        String fileId =  result.getString("shitiid");

        //创建未分发

        //SwLaihanZhuServiceImpl.createOrUpdateSwLaihanZhuVO(SwLanhanAllDTO swLanhanAllDTO);

        return true;
    }
}
